package edu.ccut.saturn.component;

import java.text.ParseException;
import java.util.Date;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;

import edu.ccut.saturn.component.utils.DateUtils;

/**
 * 任务
 * <li>字段key：唯一标识一个任务，该key值由【待执行任务的fullkey + 系统时间 + 时间的毫秒】组成
 * <li>字段jobDetail：记录该任务要执行的具体内容、参数信息以及job属性。
 * <li>字段trigger：记录该任务的触发器，即任务的执行时间，执行次数，执行间隔等信息。其中，开始时间和结束时间的格式为年-月-日 时：分：秒
 * <li>字段state：记录该任务的状态。
 * <li>字段loadStart：记录该任务是否加载启动。
 * 
 * @author 李佳伦
 * 
 * @version 1.0 2009.6.12
 * 
 * @see IComponentInfo
 */

public class SaturnTask {

	private static final String LOGGER_KEY_COMPONENT_RUNTIME = SaturnLoggerManager.LOGGER_KEY_COMPONENT_RUNTIME;

	protected static ILogger logger = SaturnLoggerManager.getInstance()
			.getSaturnLogger(LOGGER_KEY_COMPONENT_RUNTIME);

	private String key;

	private JobDetail jobDetail;

	private Trigger trigger;

	private String state;

	private String loadStart;

	public static String getLOGGER_KEY_COMPONENT_RUNTIME() {
		return LOGGER_KEY_COMPONENT_RUNTIME;
	}

	public static ILogger getLogger() {
		return logger;
	}

	public String getLoadStart() {
		return loadStart;
	}

	public void initTask(SaturnData taskSaturnData,
			IParameterContext parameterContext) throws Exception {

		String name = DateUtils.getSystemTime() + System.currentTimeMillis();

		this.key = taskSaturnData.getString("componentFullKey") + name;

		initJobDetail(name, taskSaturnData, parameterContext);

		if (taskSaturnData.getString("cronExpression") == null
				|| "".equals(taskSaturnData.getString("cronExpression"))) {
			this.trigger = initSimpleTrigger(name, taskSaturnData);
		} else {
			this.trigger = initCronTrigger(name, taskSaturnData);
		}
	}

	private void initJobDetail(String name, SaturnData taskSaturnData,
			IParameterContext parameterContext) {
		this.jobDetail = new JobDetail(name, taskSaturnData
				.getString("componentFullKey"),
				edu.ccut.saturn.component.SaturnTaskJob.class);
		this.jobDetail.getJobDataMap().put("logicfullkey",
				taskSaturnData.getString("componentFullKey"));
		this.jobDetail.getJobDataMap().put("parameterContext",
				parameterContext.newParameterContext());
		this.jobDetail.setDurability(true);
	}

	private SimpleTrigger initSimpleTrigger(String name, SaturnData taskSaturnData)
			throws Exception {
		String componentFullKey = taskSaturnData.getString("componentFullKey");

		if (componentFullKey == null || "".equals(componentFullKey)) {
			throw new SaturnComponentException("init trigger failed !!");
		}

		SimpleTrigger simpleTrigger = new SimpleTrigger(name, componentFullKey);
		Date startTime = this.getStartTime(taskSaturnData);
		Date endTime = this.getTime(taskSaturnData.getString("endTime"));
		long repeatInterval = this.getRepeatInterval(taskSaturnData);
		int repeatCount = this.getRepeatCount(taskSaturnData);

		simpleTrigger.setStartTime(startTime);

		if (endTime == null) {			
			if (repeatInterval >= 0) {
				simpleTrigger.setRepeatCount(repeatCount);
				simpleTrigger.setRepeatInterval(repeatInterval);
			} else {
				throw new SaturnComponentException("init trigger failed !!");
			}			
		} else {
			if (repeatInterval >= 0) {
				simpleTrigger.setEndTime(endTime);
				simpleTrigger.setRepeatInterval(repeatInterval);
				// 在开始时间和结束时间之间按频率执行
			} else {
				throw new SaturnComponentException("init trigger failed !!");
			}
		}

		return simpleTrigger;
	}

	private int getRepeatCount(SaturnData taskSaturnData) {
		if ("".equals(taskSaturnData.getString("repeatCount"))
				|| taskSaturnData.getString("repeatCount") == null) {
			return SimpleTrigger.REPEAT_INDEFINITELY;
		}
		return Integer.parseInt(taskSaturnData.getString("repeatCount"));
	}

	private Date getStartTime(SaturnData taskSaturnData) throws Exception {

		if (this.getTime(taskSaturnData.getString("startTime")) == null) {
			return new Date();
		}

		return this.getTime(taskSaturnData.getString("startTime"));
	}

	private long getRepeatInterval(SaturnData taskSaturnData) {
		if ("".equals(taskSaturnData.getString("repeatUnit"))
				|| "".equals(taskSaturnData.getString("repeatInterval"))
				|| taskSaturnData.getString("repeatUnit") == null
				|| taskSaturnData.getString("repeatInterval") == null) {
			return -1;
		}

		long repeatInterval = Long.parseLong((taskSaturnData
				.getString("repeatInterval")));

		if (IComponentInfo.REPEAT_UNIT_SECOND.equals(taskSaturnData
				.getString("repeatUnit"))) {
			repeatInterval = repeatInterval * 1000L;
		}

		if (IComponentInfo.REPEAT_UNIT_MINUTE.equals(taskSaturnData
				.getString("repeatUnit"))) {
			repeatInterval = repeatInterval * 60 * 1000L;
		}

		if (IComponentInfo.REPEAT_UNIT_HOUR.equals(taskSaturnData
				.getString("repeatUnit"))) {
			repeatInterval = repeatInterval * 60 * 60 * 1000L;
		}

		if (IComponentInfo.REPEAT_UNIT_DAY.equals(taskSaturnData
				.getString("repeatUnit"))) {
			repeatInterval = repeatInterval * 24 * 60 * 60 * 1000L;
		}
		return repeatInterval;
	}

	private CronTrigger initCronTrigger(String name, SaturnData taskSaturnData)
			throws Exception {
		Date startTime;
		Date endTime;

		if (taskSaturnData.getString("startTime") == null
				|| "".equals(taskSaturnData.getString("startTime"))) {
			startTime = new Date();
		} else {
			startTime = this.getTime(taskSaturnData.getString("startTime"));
		}

		if (taskSaturnData.getString("endTime") == null
				|| "".equals(taskSaturnData.getString("endTime"))) {
			endTime = null;
		} else {
			endTime = this.getTime(taskSaturnData.getString("endTime"));
		}

		CronTrigger cronTrigger = new CronTrigger(name, taskSaturnData
				.getString("componentFullKey"));

		try {
			cronTrigger.setCronExpression(taskSaturnData
					.getString("cronExpression"));
			if (startTime != null || endTime != null) {
				cronTrigger.setStartTime(startTime);
				cronTrigger.setEndTime(endTime);
			}
		} catch (ParseException e) {
			logger.debug("cron expression validate !when execute timer "
					+ getKey(), e);
		}

		return cronTrigger;
	}

	public JobDetail getJobDetail() {
		return this.jobDetail;
	}

	public Trigger getTrigger() {
		return this.trigger;
	}

	public String getKey() {
		return key;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	private Date getTime(String fullTime) throws Exception {
		if (fullTime == null || "".equals(fullTime)) {
			return null;
		}
		String[] dateAndTime = fullTime.split(" ");
		String[] date = dateAndTime[0].split("-");
		String[] time = dateAndTime[1].split(":");

		return TriggerUtils.getDateOf(Integer.parseInt(time[2]), Integer
				.parseInt(time[1]), Integer.parseInt(time[0]), Integer
				.parseInt(date[2]), Integer.parseInt(date[1]), Integer
				.parseInt(date[0]));

	}
}
